package Server;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Date;
import java.util.PriorityQueue;

import javax.swing.Timer;

import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;

import Server.Date.ReadWriteTextFile;

public class ServerHandler extends IoHandlerAdapter implements ActionListener
{

	boolean debug=true;
	ArrayList<IoSession> sessions;
	ArrayList<Subscription> subscriptions;
	PriorityQueue<String> queue;
	Timer timer;
	public int deltaT=100;// miliseconds
	Notifier notifier;
	Subscription subscription;
	Pool pool;
	Supplier supplier;
	public ServerHandler(ReadWriteTextFile rd){
		pool=new Pool();
		for(int i=0;i<30;i++){
			pool.add(new Subscription(null));
		}
		sessions=new ArrayList<IoSession>();
		subscriptions=new ArrayList<Subscription>();
		queue=new PriorityQueue<String>();
		notifier=new Notifier(queue,subscriptions);
		//timer=new Timer(deltaT,this);
		//timer.start();

		System.out.println("111");
		supplier=new Supplier(rd,this);
		System.out.println("222");
	}
	
	@Override
    public void exceptionCaught( IoSession session, Throwable cause ) throws Exception
    {
        cause.printStackTrace();
    }

    @Override
    public void messageReceived( IoSession session, Object message ) throws Exception
    {
    	System.out.println(message);
        String str = message.toString();
        if( str.trim().equalsIgnoreCase("quit") ) {
            session.close();
            return;
        }else if(str.trim().equalsIgnoreCase("subscribe") ) {
        	if(pool.isEmpty()){
        		System.out.println("...initializing...");
        		subscription=new Subscription(session);
        	}else{
        		System.out.println("...geting from pool...");
        		subscription=pool.get();
        		subscription.init(session);
        	}
        	subscriptions.add(subscription);
        	printSubscriptions("Subscriptions");
        	System.out.println(session+" : has subscribed");
        }else if(str.trim().equalsIgnoreCase("unsubscribe") ) {
        	removeSubscriptionWithSession(session);
        	printSubscriptions("Subscriptions");
        	System.out.println(session+" : has unsubscribed");
        }else if(str.trim().equalsIgnoreCase("done") ) {
        	freeQueue(session);
        }

        //Date date = new Date();
        //session.write( date.toString() );
        System.out.println("Message written...");
    }

    @Override
    public void sessionIdle( IoSession session, IdleStatus status ) throws Exception
    {
        System.out.println( "IDLE " + session.getIdleCount( status ));
    }
    
    @Override
    public void sessionOpened(IoSession session){
    	sessions.add(session);
    	printSessions("Opened Sessions");
    	System.out.println(session+" : was opened");
    }
    @Override
    public void sessionClosed(IoSession session){
    	sessions.remove(session);
    	removeSubscriptionWithSession(session);
    	printSessions("Opened Sessions");
    	System.out.println(session+" : was closed");
    }
    
    // output functions
    public void printSessions(String msg){
    	if(debug){
    		System.out.println("-----------------------------------------------------------------------");
    		if(sessions.size()!=0){
    			System.out.println(msg);
    			for(int i=0;i<sessions.size();i++){
    				System.out.print("|");
    				printSession(sessions.get(i));
    				System.out.println("|");
    			}
    		}else{
    			System.out.println("No Opened Sessions");
    		}
    		System.out.println("-----------------------------------------------------------------------");
    	}
    }
    public void printSubscriptions(String msg){
    	if(debug){
    		System.out.println("-----------------------------------------------------------------------");
    		if(subscriptions.size()!=0){
    			System.out.println(msg);
    			for(int i=0;i<subscriptions.size();i++){
    				System.out.print("|");
    				printSession(subscriptions.get(i).getSession());
    				System.out.println("|");
    			}
    		}else{
    			System.out.println("No Subscriptions");
    		}
    		System.out.println("-----------------------------------------------------------------------");
    	}
    }
    public void printSession(IoSession session){
    	System.out.print(session);
    }

    
    //do action
    public void doAction(String s){
		addToQueue(s);
	}
    
    // timer event
	public void actionPerformed(ActionEvent e){
		if(e.getSource()==timer){
			addToQueue("Nr. "+Math.random());
			//sendToAll(Math.random() + " is a random number.");
		}
	}
	private void addToQueue(String s){
		queue.add(s);
	}

	private synchronized void removeSubscriptionWithSession(IoSession s){
		for(int i=0;i<subscriptions.size();i++){
			if(subscriptions.get(i).getSession().equals(s)){
				subscriptions.get(i).stopMe();
				subscriptions.remove(i);
				return;
			}
		}
	}
	private synchronized void freeQueue(IoSession s){
		for(int i=0;i<subscriptions.size();i++){
			if(subscriptions.get(i).getSession().equals(s)){
				subscriptions.get(i).canSend=true;
				return;
			}
		}
	}
    
}

